package com.phs.main.web.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.phs.main.common.constant.AjaxResult;
import com.phs.main.common.documents.ExcelUtil;
import com.phs.main.common.utils.SaltUtil;
import com.phs.main.security.jwt.JWTToken;
import com.phs.main.security.jwt.JWTUtil;
import com.phs.main.vo.*;
import com.phs.main.web.po.*;
import com.phs.main.web.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;


/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author Trent
 * @since 2020-07-07
 */
@Api
@RestController
@RequestMapping("/sysUsers")
public class SysUsersController {
	@Lazy
	@Autowired
	ISysUsersService usersService;
	@Lazy
	@Autowired
	ISysUsersRolesService usersRolesService;
	@Lazy
	@Autowired
	ISysRolesService rolesService;
	@Lazy
	@Autowired
	ISysRolesPermissionsService rolesPermissionsService;
	@Lazy
	@Autowired
	ISysPermissionsService permissionsService;
	@Lazy
	@Autowired
	IPropertyInformationService propertyInformationService;

	@ApiOperation(value = "注册业主")
	//属于user或者admin之一;修改logical为OR 即可
	@RequiresRoles(value = {"user", "admin"}, logical = Logical.OR)
//	@RequiresPermissions(value = {"user:find"})
	@PostMapping("/addOwner")
	public AjaxResult addOwner(@RequestBody SysUsers user) {
		return save(user, 3);
	}

	@ApiOperation(value = "注册员工", notes = "根据User对象创建用户")
	@RequiresRoles(value = {"user", "admin"}, logical = Logical.OR)
	@PostMapping("/addEmployee")
	public AjaxResult addEmployee(@RequestBody SysUsers user) {
		return save(user, 4);
	}

	private AjaxResult save(SysUsers user, long roleId) {

		//	获得随机的 10位盐
		String salt = SaltUtil.getSalt(10);
		user.setSalt(salt);

		user.setPassword(JWTUtil.md5Encryption(user.getPassword(), salt));

		try {
			usersService.save(user);
			QueryWrapper<SysUsers> usersQueryWrapper = new QueryWrapper<>();
			usersQueryWrapper.eq("tel", user.getTel());

			SysUsersRoles usersRoles = new SysUsersRoles();
			usersRoles.setRoleId(roleId);
			usersRoles.setUserId(usersService.getOne(usersQueryWrapper).getUserId());

			usersRolesService.save(usersRoles);

		} catch (DuplicateKeyException e) {
			return AjaxResult.error("注册失败，已有相同手机号账号");
		} catch (Exception e) {
			return AjaxResult.error("注册失败，系统异常");
		}

		return AjaxResult.success("注册成功");
	}

	@ApiOperation(value = "删除", notes = "根据UserID删除用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id", value = "用户ID", dataType = "Long", required = true),
	})
	@DeleteMapping("/deleteById/{id}")
	public AjaxResult deleteUserById(@PathVariable long id) {
		try {
			if (usersService.removeById(id)) {
				return AjaxResult.success("已删除");
			} else {
				return AjaxResult.error("未删除");
			}
		} catch (Exception e) {
			return AjaxResult.error("出错", e.getMessage());
		}
	}

	@ApiOperation(value = "删除", notes = "根据User 电话删除用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tel", value = "用户电话", dataType = "String", required = true),
	})
	@DeleteMapping("/deleteByName/{tel}")
	public AjaxResult deleteUserByName(@PathVariable String tel) {
		try {
			QueryWrapper<SysUsers> usersQueryWrapper = new QueryWrapper<>();
			// 参数：(数据库里的列名, 参数)
			// eq：equal  =
			// eq("id",2) 就是 where id = 2

			usersQueryWrapper.eq("tel", tel);
			if (usersService.remove(usersQueryWrapper)) {
				return AjaxResult.success("已删除");
			} else {
				return AjaxResult.error("删除失败");
			}
		} catch (Exception e) {
			return AjaxResult.error("出错", e.getMessage());
		}
	}

	@ApiOperation("通过用户ID更新用户")
	@PutMapping("/updateById")
	public AjaxResult updateById(@RequestBody SysUsers user) {
		try {
			if (usersService.updateById(user)) {
				return AjaxResult.success("更改成功");
			} else {
				return AjaxResult.error("更改失败");
			}
		} catch (Exception e) {
			return AjaxResult.error("出错", e.getMessage());
		}
	}

	@ApiOperation("通过用户电话更新用户")
	@PutMapping("/updateByName")
	public AjaxResult updateByName(@RequestBody SysUsers user) {
		try {
			QueryWrapper<SysUsers> usersQueryWrapper = new QueryWrapper<>();
			usersQueryWrapper.eq("tel", user.getTel());

			if (usersService.update(user, usersQueryWrapper)) {
				return AjaxResult.success("更改成功");
			} else {
				return AjaxResult.error("更改失败");
			}
		} catch (Exception e) {
			return AjaxResult.error("出错", e.getMessage());
		}
	}

	@ApiOperation("修改密码")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "oldPassword", value = "密码", dataType = "String", required = true),
			@ApiImplicitParam(name = "newPassword", value = "密码", dataType = "String", required = true),
	})
	@RequiresRoles(value = {"user", "admin", "employee"}, logical = Logical.OR)
	@PostMapping("/changePassword")
	public AjaxResult changePassword(String oldPassword, String newPassword) {
		SysUsers user = (SysUsers) SecurityUtils.getSubject().getPrincipal();
		String entryOld = JWTUtil.md5Encryption(oldPassword, user.getSalt());
		if (entryOld.equals(user.getPassword())) {
			user.setPassword(JWTUtil.md5Encryption(newPassword, user.getSalt()));
			usersService.updateById(user);
			return AjaxResult.success("更改成功");
		} else {
			return AjaxResult.error("新旧密码不一致");
		}
	}

	@ApiOperation("获取当前登录用户权限列表")
	@RequiresRoles(value = {"user", "admin", "employee"}, logical = Logical.OR)
	@GetMapping("/getPermissions")
	public AjaxResult getPermissions() {
		return AjaxResult.success(getUP((SysUsers) SecurityUtils.getSubject().getPrincipal()));
	}

	@ApiOperation("重置密码为123456")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tel", value = "电话", dataType = "String")
	})
	@RequiresRoles(value = {"admin", "employee"}, logical = Logical.OR)
	@PostMapping("/resetPassword")
	public AjaxResult resetPassword(String tel) {
		QueryWrapper<SysUsers> wrapper = new QueryWrapper<>();
		wrapper.eq("tel", tel);
		SysUsers one = usersService.getOne(wrapper);

		if (one != null) {
			String newPsd = JWTUtil.md5Encryption("123456", one.getSalt());
			one.setPassword(newPsd);
			usersService.updateById(one);
		} else {
			return AjaxResult.error("无此用户");
		}

		return AjaxResult.success("成功");
	}

	@ApiOperation("查询所有职员")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "current", value = "页码", dataType = "Long"),
			@ApiImplicitParam(name = "size", value = "单页条数", dataType = "Long")
	})
	@RequiresRoles(value = {"user", "admin"}, logical = Logical.OR)
	@GetMapping("/findAllEmployee/{current}/{size}")
	public AjaxResult findAllEmployee(@PathVariable Long current, @PathVariable Long size) {
		QueryWrapper<SysUsersRoles> userRoleWrapper = new QueryWrapper<>();
		userRoleWrapper.ne("role_ID", 3)
				.ne("role_ID", 2)
				.ne("role_ID", 1);

		List<SysUsersRoles> userRole = usersRolesService.list(userRoleWrapper);

		QueryWrapper<SysUsers> userWrapper = new QueryWrapper<>();
		for (SysUsersRoles role : userRole) {
			userWrapper.eq("user_ID", role.getUserId()).or();
		}

		Page<SysUsers> page = new Page<>(current - 1, size);

		Page page1 = usersService.page(page, userWrapper);

		List<EmployeeVO> r = new ArrayList<>();
		page1.getRecords().forEach(user -> {
			try {
				SysUsers users = (SysUsers) user;
				r.add(new EmployeeVO(getUR(users)));
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		page1.setRecords(r);

		return AjaxResult.success(page1);
	}

	@ApiOperation("查询所有业主")
	@RequiresRoles(value = {"admin", "employee"}, logical = Logical.OR)
	@GetMapping("/findAllOwner")
	public AjaxResult findAllOwner() {
		return AjaxResult.success(usersService.getOwner());
	}

	private UserRolePerm getUR(SysUsers account) {
		//	设置角色集合
		Set<SysRoles> roles = new HashSet<>();
		//	通过UserID 获得与其关联的RolesID
		QueryWrapper<SysUsersRoles> u_r_wrapper = new QueryWrapper<>();
		u_r_wrapper.eq("user_ID", account.getUserId());

		//	返回为空时不执行lambda 语句
		List<SysUsersRoles> sysUsersRoles = usersRolesService.list(u_r_wrapper);
		sysUsersRoles.forEach(userRole -> {
			//	通过RoleID 获得Role
			QueryWrapper<SysRoles> r_wrapper = new QueryWrapper<>();
			r_wrapper.eq("role_ID", userRole.getRoleId());

			//	获得role 列表，加入roles 集合
			SysRoles rolesOne = rolesService.getOne(r_wrapper);
			roles.add(rolesOne);
		});

		return new UserRolePerm(account, roles, null);
	}

	private UserRolePerm getUP(SysUsers account) {
		//	设置权限集合
		Set<String> perms = new HashSet<>();

		//	通过UserID 获得与其关联的RolesID
		QueryWrapper<SysUsersRoles> u_r_wrapper = new QueryWrapper<>();
		u_r_wrapper.eq("user_ID", account.getUserId());

		//	返回为空时不执行lambda 语句
		List<SysUsersRoles> sysUsersRoles = usersRolesService.list(u_r_wrapper);
		sysUsersRoles.forEach(userRole -> {
			//	通过RoleID 获得Role
			QueryWrapper<SysRoles> r_wrapper = new QueryWrapper<>();
			r_wrapper.eq("role_ID", userRole.getRoleId());

			//	获得role 列表，加入roles 集合
			SysRoles rolesServiceOne = rolesService.getOne(r_wrapper);
			String roleName = rolesServiceOne.getRoleName();

			// 根据roleID 获得关联的perm ID
			QueryWrapper<SysRolesPermissions> r_p_wrapper = new QueryWrapper<>();
			r_p_wrapper.eq("role_ID", userRole.getRoleId());

			//	设置权限
			List<SysRolesPermissions> rolesPermissions = rolesPermissionsService.list(r_p_wrapper);
			rolesPermissions.forEach(rolePerm -> {
				//	通过permID 获得 permName
				QueryWrapper<SysPermissions> p_wrapper = new QueryWrapper<>();
				p_wrapper.eq("permission_ID", rolePerm.getPermissionId());
				// 获得perm
				SysPermissions permissions = permissionsService.getOne(p_wrapper);
				String permissionName = permissions.getPermissionName();

				perms.add(roleName + ":" + permissionName);
			});
		});

		return new UserRolePerm(account, null, perms);
	}

	@ApiOperation("下载业主excel")
	@GetMapping("/ownerExcel")
	public void downloadOwnerExcel(HttpServletResponse response) {
		try {
			ExcelUtil.downloadExcel("业主表" + new Date(), OwnerVO.class, response)
					.doWrite(usersService.getOwner());
		} catch (IOException e) {
			AjaxResult.success(e.getMessage());
		}
	}

	@ApiOperation("下载员工excel")
	@GetMapping("/employeeExcel")
	public void downloadEmployeeExcel(HttpServletResponse response) {
		try {
			ExcelUtil.downloadExcel("员工表" + new Date(), UserInfoVO.class, response)
					.doWrite(ConvertToVO.getVOList(
							usersService.list(),
							UserInfoVO.class
					));
		} catch (IOException e) {
			AjaxResult.success(e.getMessage());
		}
	}

	@ApiOperation(value = "查询", notes = "根据UserID查询用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id", value = "用户ID", dataType = "Long", required = true),
	})
	@RequiresRoles(value = {"employee", "admin"}, logical = Logical.OR)
	@GetMapping("/getUsrById/{id}")
	public AjaxResult getUserById(@PathVariable long id) {
		try {
			QueryWrapper<SysUsers> usersQueryWrapper = new QueryWrapper<>();
			usersQueryWrapper.eq("user_ID", id);
			SysUsers one = usersService.getOne(usersQueryWrapper);
			if (one == null) {
				return AjaxResult.error("无结果");
			}
			return AjaxResult.success("查询成功", new UserInfoVO(one));
		} catch (Exception e) {
			return AjaxResult.error("出错", e.getMessage());
		}
	}

	@ApiOperation(value = "获得当前登录用户信息")
	@GetMapping("/getUserInfo")
	public AjaxResult getUserInfo() {
		return AjaxResult.success(new UserInfoVO((SysUsers) SecurityUtils.getSubject().getPrincipal()));
	}

	@ApiOperation(value = "上传文件")
	@PostMapping("/upload")
	public AjaxResult upload(@RequestParam("file") MultipartFile file) {
		if (file.isEmpty()) {
			return AjaxResult.error("上传文件不能为空");
		}
		//上传文件 相关逻辑
		SysUsers users = ((SysUsers) SecurityUtils.getSubject().getPrincipal());
		String fileName = users.getTel();
		String filePath = "/home/ubuntu/data/upload/";

		File file1 = new File(filePath + fileName + ".jpg");
		try {
			file.transferTo(file1);
		} catch (IOException e) {
			AjaxResult.error(e.getMessage());
		}
		return AjaxResult.success();
	}

	@ApiOperation(value = "登录", notes = "根据User对象创建用户")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "username", value = "手机号", dataType = "String", required = true),
			@ApiImplicitParam(name = "password", value = "密码", dataType = "String", required = true)
	})
	@PostMapping("/login")
	public AjaxResult login(String username, String password, HttpServletResponse response) {

		String token;
		QueryWrapper<SysUsers> wrapper = new QueryWrapper<>();
		wrapper.eq("tel", username);

		//	获得盐
		SysUsers users = usersService.getOne(wrapper);
		if (users == null) {
			return AjaxResult.error("用户不存在");
		}
		//	登录
		try {
			//生成Token
			token = JWTUtil.sign(username, JWTUtil.md5Encryption(password, users.getSalt()));
			JWTToken jwtToken = new JWTToken(token);
			//	获取主体对象
			Subject subject = SecurityUtils.getSubject();
			// 执行后跳转到Realm
			subject.login(jwtToken);

		} catch (Exception e) {
			return AjaxResult.error(e.getMessage());
		}
		response.addHeader("Authorization", token);
		return AjaxResult.success("登录成功", token);
	}

	@ApiOperation("登出")
	@GetMapping("/logout")
	public AjaxResult logout() {
		SecurityUtils.getSubject().logout();
		return AjaxResult.success();
	}

}
